home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 52
/
Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso
/
Aminet
/
util
/
moni
/
Sysmon120a.lha
/
sysmon
/
src
/
UnMount.c
< prev
next >
Wrap
C/C++ Source or Header
|
2002-08-24
|
8KB
|
293 lines
/*
** $RCSfile: UnMount.c,v $
** $Filename: UnMount.c $
** $Revision: 0.1 $
** $Date: 1995/04/29 17:33:51 $
**
** Try to Shutdown or at least Inhibit DOS-Handlers (version 1.1)
**
** (C) Copyright 1995-2002 by Etienne Vogt
*/
#include <exec/alerts.h>
#include <exec/memory.h>
#include <dos/dosextens.h>
#include <dos/dostags.h>
#include <dos/filehandler.h>
#include <workbench/startup.h>
#define __USE_SYSBASE
#include <proto/exec.h>
#include <proto/dos.h>
#include <clib/alib_protos.h>
#include <string.h>
struct ExecBase *SysBase;
struct DosLibrary *DOSBase;
static struct WBStartup *wbmsg;
static struct RDArgs *myrda;
static UBYTE version[] = "$VER: UnMount 1.1 (24.8.2002)";
static UBYTE template[] = "DEVICE,INHIBIT/S,RETRY/K/N,ALL/S,FREENODE/S,QUIET/S";
#define DBUFSIZE 16
#define DNAMSIZE 24
struct devBuffer
{ struct devBuffer *dbf_Link;
UBYTE dbf_Name[DBUFSIZE][DNAMSIZE];
};
#define OPT_DEVICE 0
#define OPT_INHIBIT 1
#define OPT_RETRY 2
#define OPT_ALL 3
#define OPT_FREENODE 4
#define OPT_QUIET 5
#define OPTMAX 6
ULONG __saveds main(void);
static void cleanexit(ULONG rc);
static int unmount(STRPTR device, int inhibit, int retry, int quiet);
static struct devBuffer *getdevices(int *nodes);
static void freedbufs(struct devBuffer *dbufs);
static void killdevices(struct devBuffer *dbuf, int numdevs, int inhibit, int retry, int freenode, int quiet);
static void freeNode(STRPTR device);
static void freeWeird(BPTR bp, ULONG size);
ULONG __saveds main(void) /* No startup code */
{
struct Process *myproc;
LONG opts[OPTMAX];
ULONG rc = 0;
SysBase = *(struct ExecBase **)4;
DOSBase = NULL;
wbmsg = NULL;
myrda = NULL;
myproc = (struct Process *)FindTask(NULL);
if ((DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",36)) == NULL)
{ Alert(AT_Recovery|AG_OpenLib|AO_DOSLib);
return 100;
}
if (!(myproc->pr_CLI)) /* If started from WB, exit cleanly */
{ WaitPort(&(myproc->pr_MsgPort));
wbmsg = (struct WBStartup *)GetMsg(&(myproc->pr_MsgPort));
cleanexit(20);
}
else
{ APTR oldwinptr;
int retrycount = 10, error;
memset((char *)opts, 0, sizeof(opts));
if ((myrda = ReadArgs(template, opts, NULL)) == NULL)
{ PrintFault(IoErr(),"UnMount");
cleanexit(20);
}
if (opts[OPT_RETRY]) retrycount = *((LONG *)opts[OPT_RETRY]);
oldwinptr = myproc->pr_WindowPtr; /* Disable DOS Requesters */
myproc->pr_WindowPtr = (APTR)(-1L);
if (opts[OPT_DEVICE])
{ struct DosList *dol;
char buffer[DNAMSIZE];
STRPTR colon;
dol = LockDosList(LDF_DEVICES | LDF_READ);
strncpy(buffer, (STRPTR)opts[OPT_DEVICE], sizeof(buffer));
if (colon = (UBYTE *)strchr(buffer,':')) *colon = (UBYTE)0;
else buffer[DNAMSIZE-1] = (UBYTE)0;
if (dol = FindDosEntry(dol, buffer, LDF_DEVICES))
{ if (dol->dol_Task) /* There's a handler process running */
{ UnLockDosList(LDF_DEVICES | LDF_READ);
if (error = unmount((STRPTR)opts[OPT_DEVICE], opts[OPT_INHIBIT], retrycount, opts[OPT_QUIET]))
{ PrintFault(error, "UnMount");
rc = 10;
}
}
else UnLockDosList(LDF_DEVICES | LDF_READ);
if (opts[OPT_FREENODE]) freeNode((STRPTR)opts[OPT_DEVICE]);
}
else
{ UnLockDosList(LDF_DEVICES | LDF_READ);
PrintFault(ERROR_DEVICE_NOT_MOUNTED, "UnMount");
rc = 20;
}
}
else if (opts[OPT_ALL])
{ struct devBuffer *dbuf;
int numdevs;
if (dbuf = getdevices(&numdevs)) killdevices(dbuf, numdevs, opts[OPT_INHIBIT], retrycount, opts[OPT_FREENODE], opts[OPT_QUIET]);
else
{ PrintFault(ERROR_NO_FREE_STORE, "UnMount");
rc = 20;
}
}
else
{ PrintFault(ERROR_REQUIRED_ARG_MISSING, "UnMount");
rc = 20;
}
myproc->pr_WindowPtr = oldwinptr;
}
cleanexit(rc);
}
static void cleanexit(ULONG rc)
{
if (myrda) FreeArgs(myrda);
if (DOSBase) CloseLibrary((struct Library *)DOSBase);
if (wbmsg)
{ Forbid();
ReplyMsg((struct Message *)wbmsg);
}
Exit(rc);
}
static int unmount(STRPTR device, int inhibit, int retry, int quiet)
{ struct DevProc *dvp;
int count = 0, rc = 0;
if (!strchr(device,':')) return ERROR_INVALID_COMPONENT_NAME;
if (dvp = GetDeviceProc(device, NULL))
{ if (DoPkt0(dvp->dvp_Port, ACTION_DIE) == DOSFALSE)
{ rc = IoErr();
if (IsFileSystem(device) && inhibit)
{ if (!quiet) Printf("UnMount: Couldn't kill device %s, Trying to inhibit...\n", device);
do
{ if (Inhibit(device, DOSTRUE)) break;
else if ((rc = IoErr()) == ERROR_ACTION_NOT_KNOWN) count = retry;
else Delay(TICKS_PER_SECOND);
} while (++count < retry);
if (count < retry) rc = 0;
}
}
FreeDeviceProc(dvp);
}
else rc = IoErr();
return rc;
}
static struct devBuffer *getdevices(int *nodes)
{ struct devBuffer *dbuf;
if (dbuf = AllocVec(sizeof(struct devBuffer), MEMF_PUBLIC | MEMF_CLEAR))
{ struct DosList *dol;
struct devBuffer *db = dbuf;
int i = 0;
dol = LockDosList(LDF_DEVICES | LDF_READ);
*nodes = 0;
while (dol = NextDosEntry(dol, LDF_DEVICES))
{ UBYTE namlen;
UBYTE *namptr;
if (dol->dol_Task == NULL) continue;
namptr = BADDR(dol->dol_Name);
namlen = (namptr[0] < DNAMSIZE - 1 ? namptr[0] : DNAMSIZE - 2);
strncpy(db->dbf_Name[i], namptr + 1, namlen);
db->dbf_Name[i][namlen] = ':';
db->dbf_Name[i][namlen+1] = '\0';
if (strcmp(db->dbf_Name[i], "RAM:") == 0 || strcmp(db->dbf_Name[i], "ENV:") == 0) continue;
(*nodes)++;
if (++i == DBUFSIZE)
{ struct devBuffer *db1;
if (db1 = AllocVec(sizeof(struct devBuffer), MEMF_PUBLIC | MEMF_CLEAR))
{ db->dbf_Link = db1;
db = db1;
i = 0;
}
else
{ UnLockDosList(LDF_DEVICES | LDF_READ);
freedbufs(dbuf);
return NULL;
}
}
}
UnLockDosList(LDF_DEVICES | LDF_READ);
}
return dbuf;
}
static void freedbufs(struct devBuffer *dbufs)
{ struct devBuffer *nextdb;
do
{ nextdb = dbufs->dbf_Link;
FreeVec(dbufs);
} while (dbufs = nextdb);
}
static void killdevices(struct devBuffer *dbuf, int numdevs, int inhibit, int retry, int freenode, int quiet)
{ struct devBuffer *db = dbuf;
STRPTR devname;
int j, i, error;
for (j = 0, i = 0 ; j < numdevs ; j++)
{ devname = db->dbf_Name[i];
if (IsFileSystem(devname))
{ if (!quiet) Printf("Unmounting device %s\n", db->dbf_Name[i]);
if (error = unmount(devname, inhibit, retry, TRUE) && !quiet) PrintFault(error, "UnMount");
else if (freenode) freeNode(devname);
}
if (++i == DBUFSIZE)
{ db = db->dbf_Link;
i = 0;
}
}
freedbufs(dbuf);
}
static void freeNode(STRPTR device)
{ struct DosList *dol;
char buffer[DNAMSIZE];
STRPTR colon;
struct FileSysStartupMsg *fssm;
struct DosEnvec *de;
dol = LockDosList(LDF_DEVICES | LDF_WRITE);
strncpy(buffer, device, sizeof(buffer));
if (colon = (UBYTE *)strchr(buffer,':')) *colon = (UBYTE)0;
else buffer[DNAMSIZE-1] = (UBYTE)0;
if (dol = FindDosEntry(dol, buffer, LDF_DEVICES))
{ RemDosEntry(dol);
if (TypeOfMem(fssm = BADDR(dol->dol_misc.dol_handler.dol_Startup)) && ((ULONG)fssm & 1) == 0)
{ de = BADDR(fssm->fssm_Environ);
/* and now for some extremely bizarre assumptions... */
if (*(UBYTE *)fssm == 0 || *(UBYTE *)BADDR(fssm->fssm_Device) != 0
&& TypeOfMem(de) != 0 && (de->de_TableSize & 0xffffff00) == 0)
{ if (de->de_TableSize >= DE_CONTROL) freeWeird(de->de_Control, 0);
freeWeird(fssm->fssm_Device, 0);
freeWeird(fssm->fssm_Environ, (de->de_TableSize + 1) * sizeof(ULONG));
freeWeird(dol->dol_misc.dol_handler.dol_Startup, sizeof(struct FileSysStartupMsg));
}
else freeWeird(dol->dol_misc.dol_handler.dol_Startup, 0); /* Probably a startup string */
}
freeWeird(dol->dol_misc.dol_handler.dol_Handler, 0);
FreeDosEntry(dol);
}
UnLockDosList(LDF_DEVICES | LDF_WRITE);
}
/* From Ralph Babel's excellent Guru Book */
static void freeWeird(BPTR bp, ULONG size)
{ UBYTE *p;
if (bp)
{ p = BADDR(bp);
if (TypeOfMem(p)) /* Should point to valid memory */
{ if (((ULONG)p & MEM_BLOCKMASK) == 0) FreeMem(p, size != 0 ? size : *p + 2);
else FreeVec(p); /* Assume BCPL-style memory vector */
}
}
}